package Logika;

import java.util.Random;
import java.util.Vector;


/**
 *
 * @author mejcu
 */
public class MindServer {
    
    private int[][]         rozkladPlansza;
    private boolean[][]     boolPlansza;
    private int [][]        rozkladTank = new int[Zmienne.SZEROKOSC][Zmienne.WYSOKOSC];
    private Vector          clientTank=new Vector();
    private Vector          clientAddress=new Vector();
    private Kodowanie       kod=new Kodowanie();
    private Random random = new Random();
    private int[] values=new int[3];

public boolean[] deadPlayers={false, false, false, false};
   	public MindServer()
    	{
    		rozkladPlansza=new int[][]// layout of the game
       		{
        	{2,2,2,2,2,2,0,0,0,0,1,6 },
       	 	{2,2,2,2,0,0,0,0,0,0,1,1 },
        	{2,7,7,7,7,3,0,7,7,7,7,0 },
        	{2,3,3,3,7,3,0,3,3,3,7,0},
        	{1,3,3,3,7,3,0,3,3,7,3,0},
        	{1,3,7,7,7,7,0,3,7,3,3,0},
        	{1,3,7,3,7,3,0,7,7,7,7,0},
        	{1,3,7,7,7,3,0,3,3,3,3,0},
        	{0,0,0,0,1,1,0,1,1,0,0,0 },
       	 	{0,7,3,3,3,7,0,7,7,7,3,1},
        	{0,7,7,3,7,7,0,7,3,3,3,1},
        	{0,7,3,7,3,7,0,7,7,3,3,1},
        	{0,7,3,3,3,7,0,7,3,3,3,2},
        	{0,7,3,3,3,7,0,7,7,7,3,2},
        	{1,1,0,0,0,0,0,0,2,2,2,2 },
        	{6,1,0,0,0,0,0,0,2,2,2,2 }
    		};

            
   
    		boolPlansza=new boolean[Zmienne.getSZEROKOSC()][Zmienne.getWYSOKOSC()];// boolPlansza very helpful during Mind work

    		for(int i=0 ; i < Zmienne.SZEROKOSC ; i++)
    		{
        		for(int j=0 ; j < Zmienne.WYSOKOSC ; j++ )
        		{
                        rozkladTank[i][j]=-1;
            			if((rozkladPlansza[i][j]==Zmienne.getFREE()) || (rozkladPlansza[i][j]==Zmienne.getWOOD()))
            			{
                			boolPlansza[i][j]=true;
            			}
        		}	
    		}
   	}

    public int[] getNewTankPosition()
    {
        int[] initialValues=new int[3];// first-polozenieX, second-polozenieY, third-direction
        while(true)
        {
            initialValues[0]=random.nextInt(Zmienne.SZEROKOSC);
            initialValues[1]=random.nextInt(Zmienne.WYSOKOSC);
            if(boolPlansza[initialValues[0]][initialValues[1]])
            {
                initialValues[2]=random.nextInt(4)+1;
                break;
            }
        }
        return initialValues;
    }

    /*
     * Move Method analizes data given to server and produces the output data
     *
     */

	public String move(String data, String TankAddress)
	{
		Tank tank=(Tank)clientTank.elementAt(clientAddress.indexOf(TankAddress));
        	String komunikat="";
		
		if((int)data.charAt(0)!=tank.zwrocKierunek())
		{
			komunikat=rotate(tank.zwrocPolozenieX(), tank.zwrocPolozenieY(), (int)data.charAt(0));
                	tank.pobierzZwrot((int)data.charAt(0));
		}
		else
		{
        		int dx=0, dy=0;
        		switch((int)data.charAt(0))
        		{
            			case Zmienne.TURN_NORTH:
                			dx=-1;
                			tank.pobierzZwrot(Zmienne.TURN_NORTH);
                		break;
            			case Zmienne.TURN_EAST:
                			dy=1;
                			tank.pobierzZwrot(Zmienne.TURN_EAST);
                		break;
            			case Zmienne.TURN_SOUTH:
                			dx=1;
                			tank.pobierzZwrot(Zmienne.TURN_SOUTH);
                		break;
            			case Zmienne.TURN_WEST:
                			dy=-1;
                			tank.pobierzZwrot(Zmienne.TURN_WEST);
                		break;
        		}
        		if(getBool(tank.zwrocPolozenieX()+dx,tank.zwrocPolozenieY()+dy))
        		{
            			komunikat=setRozklad(tank.zwrocPolozenieX()+dx,tank.zwrocPolozenieY()+dy, tank.zwrocPolozenieX(),tank.zwrocPolozenieY(),tank.zwrocKierunek());
            			rozkladTank[tank.zwrocPolozenieX()+dx][tank.zwrocPolozenieY()+dy]=clientAddress.indexOf(TankAddress);
                    	rozkladTank[tank.zwrocPolozenieX()][tank.zwrocPolozenieY()]=-1;
                    	tank.pobierzX(dx);
            			tank.pobierzY(dy);
        		}
		}
        	return komunikat;
	}

	public String rotate(int i, int j, int direction)// This was changed when dr Piasecki noticed bug in steering
	{
        values=getObjectDescription(rozkladPlansza[i][j]);
        String Komunikat="";
		Komunikat+=(char)i;
		Komunikat+=(char)j;
        if(values[2]!=Zmienne.getTANK_IN_WOOD())
        {
            rozkladPlansza[i][j]=Zmienne.getTANK()+direction*10+values[0]*100;
        }
        else
        {
            rozkladPlansza[i][j]=Zmienne.getTANK_IN_WOOD()+direction*10+values[0]*100;
        }
    	Komunikat+=(char)rozkladPlansza[i][j];
		return Komunikat;
	}

    //              Mind of the game
	public String setRozklad(int i , int j , int ki , int kj,int direction)
	{
    		values=getObjectDescription(rozkladPlansza[ki][kj]);
    		String Komunikat="";
    		Komunikat+=(char)i;
    		Komunikat+=(char)j;
            if(rozkladPlansza[i][j]!=Zmienne.getWOOD())
            {
                rozkladPlansza[i][j]=Zmienne.getTANK()+direction*10+values[0]*100;
            }
            else
            {
                rozkladPlansza[i][j]=Zmienne.getTANK_IN_WOOD()+direction*10+values[0]*100;
            }
    		Komunikat+=(char)rozkladPlansza[i][j];
    		boolPlansza[i][j]=false;
    		Komunikat+=(char)ki;
        	Komunikat+=(char)kj;
            if(values[2]!=Zmienne.getTANK_IN_WOOD())
            {
                rozkladPlansza[ki][kj]=Zmienne.getFREE();
            }
            else
            {
                rozkladPlansza[ki][kj]=Zmienne.getWOOD();
            }
    		Komunikat+=(char)rozkladPlansza[ki][kj];
    		boolPlansza[ki][kj]=true;
    		return Komunikat;
	}

	public String setRozkladForOpenSpace(int i , int j , int ki , int kj, int direction, boolean first_time)
	{
    		String Komunikat="";
    		Komunikat+=(char)i;
    		Komunikat+=(char)j;
    		rozkladPlansza[i][j]=(rozkladPlansza[i][j]%10!=Zmienne.getWOOD())?Zmienne.getMISSILE()+direction*10:Zmienne.getWOOD();
    		Komunikat+=(char)rozkladPlansza[i][j];
    		boolPlansza[i][j]=false;
    		Komunikat+=(char)ki;
    		Komunikat+=(char)kj;
    		if(!first_time)
        		rozkladPlansza[ki][kj]=(rozkladPlansza[ki][kj]!=Zmienne.getWOOD())?Zmienne.getFREE():Zmienne.getWOOD();
    		Komunikat+=(char)rozkladPlansza[ki][kj];
    		boolPlansza[ki][kj]=true;
    		return Komunikat;
	}

	public String setRozkladForDestroyStop(int i , int j , int ki , int kj, boolean  first_time)
	{
            String Komunikat="";
    		Komunikat+=(char)i;
    		Komunikat+=(char)j;
            values=getObjectDescription(rozkladPlansza[i][j]);
            if((values[2]==Zmienne.TANK)||(values[2]==Zmienne.TANK_IN_WOOD))
            {
                if( ((Tank)clientTank.elementAt(rozkladTank[i][j])).isAlive() )
                {
                        ((Tank)clientTank.elementAt(rozkladTank[i][j])).shot();
                }
                else
                {
                        rozkladPlansza[i][j]=(rozkladPlansza[i][j]!=Zmienne.getWOOD())?Zmienne.getFREE():Zmienne.getWOOD();
                        clientTank.removeElementAt(rozkladTank[i][j]);
                        //clientAddress.removeElementAt(rozkladTank[i][j]);
                        deadPlayers[rozkladTank[i][j]]=true;
                        rozkladTank[i][j]=-1;
                        boolPlansza[i][j]=true;
                }
                Komunikat+=(char)rozkladPlansza[i][j];
            }
            else
            {
                rozkladPlansza[i][j]=(rozkladPlansza[i][j]!=Zmienne.getWOOD())?Zmienne.getFREE():Zmienne.getWOOD();
                Komunikat+=(char)rozkladPlansza[i][j];
                boolPlansza[i][j]=true;
            }
                Komunikat+=(char)ki;
                Komunikat+=(char)kj;
    		if(!first_time)
            {
        		rozkladPlansza[ki][kj]=(rozkladPlansza[ki][kj]!=Zmienne.getWOOD())?Zmienne.getFREE():Zmienne.getWOOD();
                boolPlansza[ki][kj]=true;
            }
            else
            {
                boolPlansza[ki][kj]=false;
            }
            Komunikat+=(char)rozkladPlansza[ki][kj];
    		return Komunikat;
	}

	public String setRozkladForStop(int i , int j , int ki , int kj, boolean first_time)
	{
    		String Komunikat="";
    		Komunikat+=(char)i;
    		Komunikat+=(char)j;
    		Komunikat+=(char)rozkladPlansza[i][j];
    		boolPlansza[i][j]=false;
    		Komunikat+=(char)ki;
    		Komunikat+=(char)kj;
    		if(!first_time)
        		rozkladPlansza[ki][kj]=(rozkladPlansza[ki][kj]!=Zmienne.getWOOD())?Zmienne.getFREE():Zmienne.getWOOD();
    		Komunikat+=(char)rozkladPlansza[ki][kj];
    		boolPlansza[ki][kj]=true;
    		return Komunikat;
	}

	public String setRozkladForRange(int i , int j, boolean first_time)
	{
    		String Komunikat="";
    		Komunikat+=(char)i;
    		Komunikat+=(char)j;
    		if(!first_time)
    		{
        		Komunikat+=(char)(rozkladPlansza[i][j]=Zmienne.FREE);
        		boolPlansza[i][j]=true;
    		}
    		else
    		{
        		Komunikat+=(char)(rozkladPlansza[i][j]);
       	 		boolPlansza[i][j]=false;
    		}
    		Komunikat+=(char)i;
    		Komunikat+=(char)j;
    		Komunikat+=(char)Komunikat.charAt(2);
    		return Komunikat;
	}

	public int getRozklad(int i , int j)
	{
    		return rozkladPlansza[i][j];
	}

	public boolean getBool(int i , int j)
	{
    		if (i<0 || i>=Zmienne.SZEROKOSC || j<0 || j>=Zmienne.WYSOKOSC)
    		{
        		return false;
    		}
    		return boolPlansza[i][j];
	}

    public void setTank(int i, int j , int direction, int whichPayer,String tankAddress)
    {
            if(rozkladPlansza[i][j]==Zmienne.WOOD)
            {
                rozkladPlansza[i][j]=Zmienne.TANK_IN_WOOD+direction*10+whichPayer*100;
            }
            else
            {
                rozkladPlansza[i][j]=Zmienne.TANK+direction*10+whichPayer*100;
            }
            clientAddress.addElement(tankAddress);
            rozkladTank[i][j]=clientAddress.size()-1;
            clientTank.addElement(new Tank(i, j,direction));
            boolPlansza[i][j]=false;
    }



	public int[][] returnRozkladPlanszy()
	{
    		return rozkladPlansza;
	}

    public void remove(String address)
    {
            Tank tank=(Tank)clientTank.elementAt(clientAddress.indexOf(address));
            values=getObjectDescription(rozkladPlansza[tank.zwrocPolozenieX()][tank.zwrocPolozenieY()]);
            if(values[2]==Zmienne.TANK_IN_WOOD)
            {
                rozkladPlansza[tank.zwrocPolozenieX()][tank.zwrocPolozenieY()]=Zmienne.WOOD;
            }
            else
            {
                rozkladPlansza[tank.zwrocPolozenieX()][tank.zwrocPolozenieY()]=Zmienne.FREE;
            }
            rozkladTank[tank.zwrocPolozenieX()][tank.zwrocPolozenieY()]=-1;
            boolPlansza[tank.zwrocPolozenieX()][tank.zwrocPolozenieY()]=true;
            clientTank.removeElementAt(clientAddress.indexOf(address));
            clientAddress.removeElement(address);
    }

    public Tank getTank(String Address)
    {
            return (Tank)clientTank.elementAt(clientAddress.indexOf(Address));
    }

    public int size()
    {
        return clientAddress.size();
    }

    public String elementAt(int i)
    {
        return (String)clientAddress.elementAt(i);
    }

    public String getStoredRozlad()
    {
        return kod.kodowanie(returnRozkladPlanszy());
    }

    public boolean  getDecision(int i , int j)
    {
        if(rozkladPlansza[i][j]==Zmienne.STELL_WALL || rozkladPlansza[i][j]==Zmienne.WATER)
            return true;
        return false;
    }

    public boolean out_of_range(int i, int j)
    {
        if(i<0 || i>=Zmienne.SZEROKOSC || j<0 || j>=Zmienne.WYSOKOSC)
            return true;
        return false;
    }

    private int[]  getObjectDescription(int value)
    {
        values[0]=value/100;//postac
        int temp_value=value/10;
        values[1]=temp_value%10;//kierunek
        values[2]=value%10;//co
        System.out.println("instance= "+values[0]+" direction= "+values[1]+" what= "+values[2]);
        return values;
    }
}
